package me.zhengjie.modules.device.service.query;

import me.zhengjie.utils.PageUtil;
import me.zhengjie.modules.device.domain.AccessDevice;
import me.zhengjie.modules.device.service.dto.AccessDeviceDTO;
import me.zhengjie.modules.device.repository.AccessDeviceRepository;
import me.zhengjie.modules.device.service.mapper.AccessDeviceMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author jie
 * @date 2018-12-03
 */
@Service
@CacheConfig(cacheNames = "accessDevice")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class AccessDeviceQueryService {

    @Autowired
    private AccessDeviceRepository accessDeviceRepository;

    @Autowired
    private AccessDeviceMapper accessDeviceMapper;

    /**
     * 分页
     */
    @Cacheable(keyGenerator = "keyGenerator")
    public Object queryAll(AccessDeviceDTO accessDevice, Pageable pageable){
        Page<AccessDevice> page = accessDeviceRepository.findAll(new Spec(accessDevice),pageable);
        return PageUtil.toPage(page.map(accessDeviceMapper::toDto));
    }

    /**
     * 不分页
     */
    @Cacheable(keyGenerator = "keyGenerator")
    public Object queryAll(AccessDeviceDTO accessDevice){
        return accessDeviceMapper.toDto(accessDeviceRepository.findAll(new Spec(accessDevice)));
    }

    class Spec implements Specification<AccessDevice> {

        private AccessDeviceDTO accessDevice;

        public Spec(AccessDeviceDTO accessDevice){
            this.accessDevice = accessDevice;
        }

        @Override
        public Predicate toPredicate(Root<AccessDevice> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
            List<Predicate> list = new ArrayList<Predicate>();

            if(!ObjectUtils.isEmpty(accessDevice.getDeviceName())){
                /**
                 * 模糊
                 */
                list.add(cb.like(root.get("deviceName").as(String.class),"%"+accessDevice.getDeviceName()+"%"));
            }
            if(!ObjectUtils.isEmpty(accessDevice.getDeviceArea())){
                /**
                 * 精确
                 */
                list.add(cb.equal(root.get("deviceArea").as(Long.class),accessDevice.getDeviceArea()));
            }
            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        }
    }
}